﻿using System;
using System.Linq;
using System.ServiceModel.Activation;
using IssueVision.EntityModel;
using IssueVision.Helper;
using IssueVision.Resource;

namespace IssueVision.Service
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class PasswordResetService : IPasswordResetService
    {
        /// <summary>
        /// Get the security question based on user name
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public string GetPasswordQuestionByUserName(string userName)
        {
            using (IssueVisionEntities context = new IssueVisionEntities())
            {
                User foundUser = context.Users.FirstOrDefault(n => n.Name == userName);

                return foundUser != null ? foundUser.PasswordQuestion : null;
            }
        }

        /// <summary>
        /// Reset user password if security question and security
        /// answer match
        /// </summary>
        /// <param name="user"></param>
        public void ResetPassword(PasswordResetUser user)
        {
            // validate the user on the server side first
            user.Validate();

            using (IssueVisionEntities context = new IssueVisionEntities())
            {
                User foundUser = context.Users.FirstOrDefault(n => n.Name == user.Name);

                if (foundUser != null)
                {
                    // retrieve password answer hash and salt from database
                    string currentPasswordAnswerHash = context.GetPasswordAnswerHash(user.Name).First();
                    string currentPasswordAnswerSalt = context.GetPasswordAnswerSalt(user.Name).First();
                    // generate password answer hash
                    string passwordAnswerHash = HashHelper.ComputeSaltedHash(user.PasswordAnswer,
                        currentPasswordAnswerSalt);

                    if (string.Equals(user.PasswordQuestion, foundUser.PasswordQuestion, StringComparison.Ordinal) &&
                        string.Equals(passwordAnswerHash, currentPasswordAnswerHash, StringComparison.Ordinal))
                    {
                        // Password answer matches, so save the new user password
                        // Re-generate password hash and password salt
                        string currentPasswordSalt = HashHelper.CreateRandomSalt();
                        string currentPasswordHash = HashHelper.ComputeSaltedHash(user.NewPassword, currentPasswordSalt);

                        // re-generate passwordAnswer hash and passwordAnswer salt
                        currentPasswordAnswerSalt = HashHelper.CreateRandomSalt();
                        currentPasswordAnswerHash = HashHelper.ComputeSaltedHash(user.PasswordAnswer, currentPasswordAnswerSalt);

                        // save changes
                        context.UpdatePasswordHashAndSalt(user.Name, 
                            currentPasswordHash, currentPasswordSalt);
                        context.UpdatePasswordAnswerHashAndSalt(user.Name, 
                            currentPasswordAnswerHash, currentPasswordAnswerSalt);
                    }
                    else
                        throw new UnauthorizedAccessException(ErrorResources.PasswordQuestionDoesNotMatch);
                }
                else
                    throw new UnauthorizedAccessException(ErrorResources.NoUserFound);
            }
        }
    }
}
